package cn.nfwx.tv.widget.nfwxplayer;

import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.FrameLayout;

import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.TimeUnit;

import butterknife.ButterKnife;
import butterknife.Unbinder;
import cn.nfwx.tv.base.NFWXApplication;
import cn.nfwx.tv.events.AppointEvent;
import cn.nfwx.tv.events.PlayEvents;
import cn.nfwx.tv.fragment.callback.ActionCallback;
import cn.nfwx.tv.helper.ThreadHelper;
import cn.nfwx.tv.helper.Threader;
import cn.nfwx.tv.util.DensityUtil;
import cn.nfwx.tv.util.LogUtil;
import io.reactivex.Observable;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;

/**
 * 重构播放器控制类
 */
public abstract class NfwxVideoPlayerController extends FrameLayout implements GestureDetector.OnGestureListener, ActionCallback {

    private final static String TAG = "NfwxVideoPlayerController";

    public Context mContext;
    protected INfwxVideoPlayer mNfwxVideoPlayer;

    private GestureDetector gestureDetector;
    private int GESTURE_FLAG = 0;// 1,调节进度，2，调节音量,3.调节亮度
    private int LAST_GESTURE_FLAG = 0;
    private float x1;
    private int playingTime;
    private float lastOldY;
    private float mBrightness = -1f; // 亮度
    private static final float STEP_PROGRESS = 2f;// 设定进度滑动时的步长，避免每次滑动都改变，导致改变过快
    private static final float STEP_VOLUME = 2f;// 协调音量滑动时的步长，避免每次滑动都改变，导致改变过快
    private boolean firstScroll = false;
    private static final int GESTURE_MODIFY_PROGRESS = 1;
    private static final int GESTURE_MODIFY_VOLUME = 2;
    private static final int GESTURE_MODIFY_BRIGHT = 3;

    private long progressControlTime = -1;
    private boolean isPress;
    private View _loadingView;

    protected Unbinder unbinder;

    public NfwxVideoPlayerController(@NonNull Context context) {
        this(context, null);
    }

    public NfwxVideoPlayerController(@NonNull Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public NfwxVideoPlayerController(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mContext = context;

        View view = LayoutInflater.from(context).inflate(getLayoutId(), this, true);

        unbinder = ButterKnife.bind(mContext, view);

        gestureDetector = new GestureDetector(mContext, this);
        gestureDetector.setIsLongpressEnabled(false);

        initView();
    }

    /**
     * 获取layout 布局文件
     *
     * @return
     */
    protected abstract int getLayoutId();

    /**
     * 初始化
     */
    protected abstract void initView();

    /**
     * 初始化数据
     */
    protected abstract void initData();

    /**
     * 滑动时间移动
     *
     * @param playTime
     */
    public abstract void progressControl(long playTime, long seekTime);

    /**
     * 滑动最终时移
     *
     * @param playTime
     */
    public abstract void progressControlFinish(long playTime);

    /**
     * 声音调节
     *
     * @param currentVolume
     * @param percentage
     */
    public abstract void updateVolume(int currentVolume, int percentage);


    /**
     * 声音调节
     *
     * @param percentage
     */
    public abstract void updateBrightness(int percentage);


    /**
     * 手势左右滑动改变播放位置后，手势up或者cancel时，隐藏控制器中间的播放位置变化视图，
     * 在手势ACTION_UP或ACTION_CANCEL时调用。
     */
    protected abstract void hidePosition();

    /**
     * 手势在左侧上下滑动改变音量后，手势up或者cancel时，隐藏控制器中间的音量变化视图，
     * 在手势ACTION_UP或ACTION_CANCEL时调用。
     */
    protected abstract void hideVolume();

    /**
     * 手势在左侧上下滑动改变亮度后，手势up或者cancel时，隐藏控制器中间的亮度变化视图，
     * 在手势ACTION_UP或ACTION_CANCEL时调用。
     */
    protected abstract void hideBrightness();

    /**
     * 布局是否显示
     */
    protected abstract void controllVisable();

    /**
     * 设置状态
     *
     * @param mCurrentState
     */
    public abstract void onPlayStateChanged(int mCurrentState);

    /**
     * 播放模式
     *
     * @param mCurrentMode
     */
    public abstract void onPlayModeChanged(int mCurrentMode);

    /**
     * 上一个
     */
    public abstract void playBack();

    /**
     * 下一个
     */
    public abstract void playNext();


    /**
     * 初始化信息
     */
    protected abstract void init();

    /**
     * 销毁
     */
    protected abstract void release();

    /**
     * 重设
     */
    protected abstract void reset();

    /**
     * 更新进度，包括进度条进度，展示的当前播放位置时长，总时长等。
     */
    protected abstract void updateProgress();

    /**
     * 是否直播中
     *
     * @return
     */
    public abstract boolean isLive();

    public abstract boolean isAdvert();

    /**
     * 是否时移中
     *
     * @return
     */
    public abstract boolean isShift();

    /**
     * 是否是音频
     *
     * @return
     */
    public abstract boolean isAudio();

    /**
     * 是否剪切中
     *
     * @return
     */
    public abstract boolean isClip();

    /**
     * 是否手动暂停
     *
     * @return
     */
    public abstract boolean isHandPause();

    /**
     * 获取直播对应的时移链接
     *
     * @param timeCode
     * @return
     */
    public abstract String getTimesShiftUrl(long timeCode);

    /**
     * 重新播放
     */
    public abstract void reStart();

    /**
     * 返回操作
     *
     * @return
     */
    public abstract boolean onBackPressd();

    /**
     * 网络改变
     *
     * @param networkType
     */
    public abstract void onNetworkChange(int networkType);

    /**
     * @param intent
     */
    public abstract void onReceive(Intent intent);

    public abstract boolean isLock();

    /**
     * @param videoPlayer
     */
    public void setVideoPlayer(INfwxVideoPlayer videoPlayer) {
        mNfwxVideoPlayer = videoPlayer;
    }

    @Override
    public boolean onDown(MotionEvent e) {
        LogUtil.v(TAG, "onDown");
        firstScroll = true;
        isPress = false;
        return false;
    }


    @Override
    public void onShowPress(MotionEvent e) {
        LogUtil.v(TAG, "onShowPress");
        firstScroll = true;
        isPress = true;
    }

    @Override
    public boolean onSingleTapUp(MotionEvent e) {
        LogUtil.v(TAG, "onSingleTapUp");
        if (!isPress) {
            controllVisable();
        }
        isPress = false;
        if (firstScroll) {
            firstScroll = false;
        }
        return false;
    }

    @Override
    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
        LogUtil.v(TAG, "onScroll");
        if (e1 == null || e2 == null || mNfwxVideoPlayer == null) {
            return false;
        }
        float mOldX = e1.getX(), mOldY = e1.getY();
        int y = (int) e2.getRawY();
        if (firstScroll) {// 以触摸屏幕后第一次滑动为标准，避免在屏幕上操作切换混乱
            // 横向的距离变化大则调整进度，纵向的变化大则调整音量
            if (GESTURE_FLAG == 0) {
                if (Math.abs(distanceX) >= Math.abs(distanceY)) {
                    GESTURE_FLAG = GESTURE_MODIFY_PROGRESS;
                } else {
                    if (mOldX > getMeasuredWidth() * 3.0 / 5) {// 音量
                        GESTURE_FLAG = GESTURE_MODIFY_VOLUME;
                    } else if (mOldX < getMeasuredWidth() * 2.0 / 5) {// 亮度
                        GESTURE_FLAG = GESTURE_MODIFY_BRIGHT;
                    }
                }
            }
        }
        if (GESTURE_FLAG == GESTURE_MODIFY_PROGRESS) {// 如果每次触摸屏幕后第一次scroll是调节进度，那之后的scroll事件都处理音量进度，直到离开屏幕执行下一次操作
            // distanceX=lastScrollPositionX-currentScrollPositionX，因此为正时是快进
            if (Math.abs(distanceX) > Math.abs(distanceY)) {// 横向移动大于纵向移动
                if (distanceX >= DensityUtil.dip2px(NFWXApplication.getInstance(), STEP_PROGRESS)) {// 快退，用步长控制改变速度，可微调  
                    playingTime -= 5000;// scroll方法执行一次快退3秒
                } else if (distanceX <= -DensityUtil.dip2px(NFWXApplication.getInstance(), STEP_PROGRESS)) {// 快进
                    playingTime += 5000;// scroll执行一次快进3秒
                }
                if (!isLive() && !mNfwxVideoPlayer.isIdle()) { // 点播时间移动
                    if (progressControlTime == -1) {
                        progressControlTime = mNfwxVideoPlayer.getCurrentPosition();
                    }
                    long seekCurrentTime = progressControlTime + playingTime;
                    if (seekCurrentTime < 0) {
                        seekCurrentTime = 0;
                    } else if (seekCurrentTime > mNfwxVideoPlayer.getDuration()) {
                        seekCurrentTime = mNfwxVideoPlayer.getDuration();
                    }
                    progressControl(seekCurrentTime, playingTime);
                }
            }
        } else if (GESTURE_FLAG == GESTURE_MODIFY_VOLUME) {// 如果每次触摸屏幕后第一次scroll是调节音量，那之后的scroll事件都处理音量调节，直到离开屏幕执行下一次操作
            if (isLock()) {
                return false;
            }
            if (Math.abs(distanceY) > Math.abs(distanceX)) {// 纵向移动大于横向移动
                int currentVolume = mNfwxVideoPlayer.getVolume();
                if (distanceY >= DensityUtil.dip2px(NFWXApplication.getInstance(), STEP_VOLUME)) {// 音量调大,注意横屏时的坐标体系,尽管左上角是原点，但横向向上滑动时distanceY为正
                    if (currentVolume < mNfwxVideoPlayer.getMaxVolume()) {// 为避免调节过快，distanceY应大于一个设定值
                        currentVolume++;
                    }
                } else if (distanceY <= -DensityUtil.dip2px(NFWXApplication.getInstance(), STEP_VOLUME)) {// 音量调小
                    if (currentVolume > 0) {
                        currentVolume--;
                    }
                }
                if (!mNfwxVideoPlayer.isIdle() && mNfwxVideoPlayer.getMaxVolume() != 0) {
                    int percentage = (currentVolume * 100) / mNfwxVideoPlayer.getMaxVolume();
                    updateVolume(currentVolume, percentage);
                    mNfwxVideoPlayer.setVolume(currentVolume);
                }
            }
        } else if (GESTURE_FLAG == GESTURE_MODIFY_BRIGHT) {// 如果每次触摸屏幕后第一次scroll是调节亮度，那之后的scroll事件都处理亮度调节，直到离开屏幕执行下一次操作
            if (isLock()) {
                return false;
            }
            if (lastOldY != mOldY) {
                lastOldY = mOldY;
                mBrightness = mNfwxVideoPlayer.getBright();
            }
            if (mBrightness < 0) {
                if (mBrightness <= 0.00f)
                    mBrightness = 0.50f;
                if (mBrightness < 0.01f)
                    mBrightness = 0.01f;
            }
            float percentage = mBrightness + (mOldY - y) / getMeasuredHeight();
            if (percentage > 1.0f)
                percentage = 1.0f;
            else if (percentage < 0.01f)
                percentage = 0.01f;
            mNfwxVideoPlayer.setBright(percentage);
            updateBrightness((int) (percentage * 100));
        }
        if (GESTURE_FLAG == 0) {
            return false;
        } else {
            if (GESTURE_FLAG == GESTURE_MODIFY_PROGRESS) {
                if (isLive()) {
                    return false;
                }
            }
            return true;
        }
    }

    @Override
    public void onLongPress(MotionEvent e) {

    }

    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
        return true;
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            return super.onInterceptTouchEvent(event);
        } else if (event.getAction() == MotionEvent.ACTION_MOVE) {
            return gestureDetector.onTouchEvent(event);
        } else if (event.getAction() == MotionEvent.ACTION_UP) {
            //return gestureDetector.onTouchEvent(event);
        }
        return super.onInterceptTouchEvent(event);
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            LogUtil.v(TAG, "dispatchTouchEvent--MotionEvent.ACTION_DOWN");
            gestureDetector.onTouchEvent(event);
        } else if (event.getAction() == MotionEvent.ACTION_MOVE) {
            LogUtil.v(TAG, "dispatchTouchEvent--MotionEvent.ACTION_MOVE");
        } else if (event.getAction() == MotionEvent.ACTION_UP) {
            LogUtil.v(TAG, "dispatchTouchEvent--MotionEvent.ACTION_UP");
            if (GESTURE_FLAG != 0) {
                onTouchEvent(event);
            }
        }
        return super.dispatchTouchEvent(event);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        // 手势里除了singleTapUp，没有其他检测up的方法
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            x1 = event.getRawX();
            LogUtil.v(TAG, "onTouchEvent--MotionEvent.ACTION_DOWN");
        } else if (event.getAction() == MotionEvent.ACTION_MOVE) {
            LogUtil.v(TAG, "onTouchEvent--MotionEvent.ACTION_MOVE");
        } else if (event.getAction() == MotionEvent.ACTION_UP) {
            LogUtil.v(TAG, "onTouchEvent--MotionEvent.ACTION_UP");
            LAST_GESTURE_FLAG = GESTURE_FLAG;
            // 时移
            if (LAST_GESTURE_FLAG == GESTURE_MODIFY_PROGRESS) {
                if (!isLive()) {
                    if (progressControlTime != -1) {
                        long seekCurrentTime = progressControlTime + playingTime;
                        if (seekCurrentTime < 0) {
                            seekCurrentTime = 0;
                        } else if (seekCurrentTime > mNfwxVideoPlayer.getDuration()) {
                            seekCurrentTime = mNfwxVideoPlayer.getDuration();
                        }
                        progressControlFinish(seekCurrentTime);
                        progressControlTime = -1;
                    }
                } else {
                    float d = event.getRawX() - x1;
                    if (Math.abs(d) > 150) {
                        if (playingTime > 0) {
                            //playBack();
                        } else if (playingTime < 0) {
                            //playNext();
                        }
                    }
                }
            }
            playingTime = 0;
            GESTURE_FLAG = 0;// 手指离开屏幕后，重置调节音量或进度的标志
            hidePosition();
            hideBrightness();
            hideVolume();
            if (LAST_GESTURE_FLAG != 0) {
                LAST_GESTURE_FLAG = 0;
                return true;
            } else {
                return gestureDetector.onTouchEvent(event);
            }
        }
        return gestureDetector.onTouchEvent(event);
    }

    private final int ACTION_TIME_UPDATE = 1;
    protected Handler mProgressTimer = new Handler(new Handler.Callback() {
        @Override
        public boolean handleMessage(Message msg) {
            switch (msg.what) {
                case ACTION_TIME_UPDATE:
                    updateProgress();
                    if (!isHandPause()) {
                        mProgressTimer.removeMessages(ACTION_TIME_UPDATE);
                        mProgressTimer.sendEmptyMessageDelayed(ACTION_TIME_UPDATE, 1000);
                    }
                    break;
            }
            return false;
        }
    });

    /**
     * 取消更新进度的计时器。
     */
    protected void cancelUpdateProgressTimer() {
        mProgressTimer.removeMessages(ACTION_TIME_UPDATE);
        mProgressTimer.removeCallbacksAndMessages(null);
    }

    /**
     * 开启更新进度的计时器。
     */
    protected void startUpdateProgressTimer() {
        cancelUpdateProgressTimer();
        mProgressTimer.sendEmptyMessage(ACTION_TIME_UPDATE);
    }


    protected <T extends View> T findView(int rid) {
        return findViewById(rid);
    }

    protected <T extends View> T findView(View view, int rid) {
        return view.findViewById(rid);
    }

    /**
     * 设置loadingview
     *
     * @param v
     * @param width
     * @param height
     */
    public void setLoadingView(View v, int width, int height) {
        if (v == null) return;
        if (v == _loadingView) return;
        if (_loadingView != null) this.removeView(_loadingView);
        _loadingView = v;
        if (width == 0) width = LayoutParams.WRAP_CONTENT;
        if (height == 0) height = LayoutParams.WRAP_CONTENT;
        LayoutParams l = new LayoutParams(width, height);
        l.gravity = Gravity.CENTER;
        this.addView(v, 0);
        v.setLayoutParams(l);
        v.requestLayout();
        hideLoading();
    }

    /**
     * 显示loadingview
     */
    protected void showLoading() {
        if (_loadingView != null) {
            _loadingView.setVisibility(VISIBLE);
        }
    }

    /**
     * 隐藏loadingview
     */
    protected void hideLoading() {
        if (_loadingView != null) {
            _loadingView.setVisibility(INVISIBLE);
        }
    }

    /**
     * 播放事件
     *
     * @param events
     */
    public void playEventBus(PlayEvents events) {
    }

    public void appiontEvent(AppointEvent event) {
    }
}
